package com.service.advice;

import com.domain.ex.BizException;
import com.domain.ex.Codes;
import com.domain.myenum.AuctionStatusEnum;
import com.domain.myenum.MsgTypeEnum;
import com.dto.*;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.handler.email.Email;
import com.handler.email.EmailHandler;
import com.job.AuctionJob;
import com.mapper.generator.ShAdviceMapper;
import com.mapper.self.*;
import com.pojo.ShAdvice;
import com.pojo.ShCompany;
import com.pojo.ShSet;
import com.service.user.UserService;
import com.utils.DateUtils;
import com.utils.RandomUtils;
import org.apache.commons.lang.StringUtils;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;

/**
 * Created by Huoyunren on 2016/2/27.
 */
@Service
public class AdviceServiceImpl implements AdviceService {

  @Autowired
  private ShAdviceMapper shAdviceMapper;
  @Autowired
  private CompanyMapper companyMapper;
  @Autowired
  private AdviceMapper adviceMapper;
  @Autowired
  private NoteMapper noteMapper;
  @Autowired
  private EmailHandler emailHandler;
  @Autowired
  private Scheduler scheduler;
  @Autowired
  private UserService userService;
  @Autowired
  private SetMapper setMapper;

  @Override
  public NoteDto add(String email, String content, Integer msgType, BigDecimal fee, Integer isShowMobile, String endTime,String img,String address) {
    validateAuction(msgType, fee, endTime, address);
    ShCompany shCompany = companyMapper.queryByEmail(email);
    if (shCompany == null){
      throw BizException.create(Codes.SystemDeclare, "没有查询到用户信息");
    }
    if (msgType == MsgTypeEnum.Auction.getCode() || msgType == MsgTypeEnum.Reward.getCode()){
      if (StringUtils.isBlank(shCompany.getPhone())) {
        throw BizException.create(Codes.SystemDeclare, "请先完善手机号");
      }
    }
    Date now = new Date();
    ShAdvice shAdvice = new ShAdvice();
    shAdvice.setEmail(email);
    shAdvice.setContent(content);
    shAdvice.setCreatetime(now);
    String uuid = RandomUtils.getUuid();
    shAdvice.setUuid(uuid);
    shAdvice.setMsgType(msgType);
    shAdvice.setFee(fee);
    shAdvice.setImg(img);
    shAdvice.setAddress(address);
    if (StringUtils.isNotBlank(endTime)){
      shAdvice.setEndTime(DateUtils.parseDate("", endTime));
    }
    shAdvice.setIsShowMobile(isShowMobile);
    shAdvice.setName(shCompany.getName());
    shAdvice.setStatus(AuctionStatusEnum.On.getCode());
    int ret = shAdviceMapper.insert(shAdvice);
    addAuctionJob(msgType, endTime, uuid,shAdvice.getEmail());
    NoteDto noteDto = new NoteDto();
    noteDto.setContent(content);
    noteDto.setCreateTime(DateUtils.getFormatDate("",now));
    noteDto.setEmail(email);
    noteDto.setLogo(shCompany.getLogo());
    noteDto.setName(shCompany.getName());
    noteDto.setUuid(uuid);

    noteNotify(content,shCompany.getName(),shCompany.getEmail());

    return noteDto;
  }


  private void noteNotify(String content, Object name, String email) {
    String alias = email;
    if (name != null) {
      alias = name.toString();
    }
    Email e = new Email();
    String[] to = {"mrliufox@foxmail.com"};
    e.setTo(to);
    e.setSubject(alias + " 发表留言");
    e.setEnableHtml(Boolean.FALSE);
    StringBuffer buffer = new StringBuffer();
    buffer.append("留言内容：");
    buffer.append(content);
    buffer.append("\n");
    buffer.append("更多详情：http://liuyuanwai.cn");
    e.setContent(buffer.toString());
    emailHandler.asyncSendMail(e);
  }

  private void validateAuction(Integer msgType, BigDecimal fee, String endTime, String address) {
    if (msgType == MsgTypeEnum.Auction.getCode()) {
      // - 拍卖
      if (fee == null){
        throw BizException.create(Codes.ParamError, "起拍价不能为空");
      }
      if (StringUtils.isBlank(address)) {
        throw BizException.create(Codes.ParamError, "交易地点不能为空");
      }
      if (StringUtils.isBlank(endTime)) {
        throw BizException.create(Codes.ParamError, "选择拍卖终止时间");
      }
      if (endTime.compareTo(DateUtils.getFormatDate("")) < 0) {
        throw BizException.create(Codes.ParamError, "拍卖终止时间不得小于当前时间");
      }
    }
  }

  private void addAuctionJob(Integer msgType, String endTime, String uuid,String auctionEmail) {
    if (msgType == MsgTypeEnum.Auction.getCode()) {
      // - 拍卖，添加定时任务在拍卖结束时评出赢得拍卖的用户
      this.addSchedulerJob(AuctionJob.class, DateUtils.parseDate("", endTime), uuid,auctionEmail);
    }
  }

  // - 查询消息列表
  @Override
  public Object list(Integer page, Integer limit,Integer type,Integer status,String email) {
    if (page == null){
      page = 1;
    }
    if (limit == null){
      limit = 10;
    }
    if (page > 0) {
      page = page - 1;
    }
    List<UserAdviceDto> advices = adviceMapper.list(page * limit, limit, email,type,status);
    Set<String> uuids = Sets.newHashSet();
    for (UserAdviceDto advice : advices) {
      if (StringUtils.isNotBlank(advice.getDealTime())) {
        advice.setDealTime(advice.getDealTime().substring(0, advice.getDealTime().length() - 2));
      }
      if (StringUtils.isNotBlank(advice.getEndTime())) {
        advice.setEndTime(advice.getEndTime().substring(0, advice.getEndTime().length() - 2));
      }
      uuids.add(advice.getUuid());
    }
    if (!CollectionUtils.isEmpty(uuids)) {
      List<NoteDto> notes = noteMapper.queryByUuid(uuids);
      Map<String/*uuid*/, List<NoteDto>> map = Maps.newHashMap();
      for (NoteDto note : notes) {
        note.setCreateTime(note.getCreateTime().substring(0, note.getCreateTime().length() - 2));
        if (!map.containsKey(note.getUuid())) {
          map.put(note.getUuid(), Lists.<NoteDto>newArrayList());
        }
        map.get(note.getUuid()).add(note);
      }
      for (UserAdviceDto advice : advices) {
        advice.setNotes(map.get(advice.getUuid()));
      }
    }
    return advices;
  }

  @Override
  public Object reward(String uuid, String dealEmail, String rewardEmail) {
    ShCompany company = companyMapper.queryByEmail(dealEmail);
    userService.validateUserInfoCompleted(company);
    Date date = DateUtils.currentDate();
    adviceMapper.reward(uuid, dealEmail, date);
    RewardDto rewardDto = new RewardDto();
    rewardDto.setName(company.getName());
    rewardDto.setPhone(company.getPhone());
    rewardDto.setEmail(dealEmail);
    rewardDto.setTime(DateUtils.getFormatDate("", date));
    // - 邮件通知悬赏人
    rewardNotify(rewardEmail, rewardDto.getName(), rewardDto.getPhone(), rewardDto.getTime(),rewardDto.getEmail());
    return rewardDto;
  }

  @Override
  public void rewardNotify(String rewardEmail, String dealName, String dealPhone, String dealTime,String dealEmail) {
    Email email = new Email();
    email.setEnableHtml(Boolean.TRUE);
    email.setSubject("揭榜通知");
    String[] to = {rewardEmail};
    email.setTo(to);
    email.setTemplate("reward.ftl");
    Map<String, Object> map = Maps.newHashMap();
    map.put("name", dealName);
    map.put("phone", dealPhone);
    map.put("time", dealTime);
    map.put("email",dealEmail);
    email.setMap(map);
    emailHandler.asyncSendMail(email);
  }

  @Override
  public AdviceDto queryByUuid(String uuid) {
    return adviceMapper.queryByUuid(uuid);
  }

  private void addSchedulerJob(Class<? extends Job> clazz, Date executeDate, String uuid,String auctionEmail) {
    try {
      if (scheduler.checkExists(JobKey.jobKey(uuid))) {
        return;
      }
      JobDetail job = JobBuilder
        .newJob(clazz)
        .withIdentity(uuid)
        .usingJobData("uuid", uuid)
        .usingJobData("auctionEmail",auctionEmail)
        .build();
      Trigger trigger = TriggerBuilder
        .newTrigger()
        .withIdentity(uuid)
        .startAt(executeDate)
        .build();
      scheduler.scheduleJob(job, trigger);
    } catch (SchedulerException e) {
      e.printStackTrace();
    }
  }
}
